package implementation;

import interfaces.HostInterface;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import algortims.EditDistance;
import entility.Job;
import entility.JobImpl;
import entility.Machine;
import entility.Notification;

public class HostImpl implements HostInterface	 {

	public static Machine meMyselfandI;

	public static List<Machine>servers;
	public static Machine primaryServer;
	public static List<Machine> buckaps;
	
	public static EditDistance distance;
	public static String head = "null";
	public static Queue<Integer> numbers;


	private static HostImpl instance;


	public Machine getMeMyselfandI() {

		return meMyselfandI;
	}

	public void setMeMyselfandI(Machine machine) {
		meMyselfandI = machine;
	}

	public Machine getPrimaryServer() {
		return primaryServer;
	}

	public void setPrimaryServer(Machine pServer) {
		primaryServer = pServer;
	}

	public static JobController jobController;

	private HostImpl(Machine machine)
	{
		meMyselfandI = machine;
		jobController = JobController.getInstance();
		numbers = new ConcurrentLinkedQueue<Integer>();

	}

	
	
	public void execute(Job job) {
		
		Thread thread = new ThreadExecute(job);
		thread.start();
	}


	

	private void start(Machine pServer) throws ClassNotFoundException, IOException {

		primaryServer = pServer;
		this.registerInServer();
		try {
			servers =  pServer.getSubServers("getServers", Notification.HOST);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void registerInServer()
	{
		try{
			Job job = new JobImpl(Notification.HOST);
			job.setMethod("addHost");
			String str = meMyselfandI.ip + ":" +meMyselfandI.port;
			List<String> data = new ArrayList<String>();
			data.add(str);
			job.setData(data);
			primaryServer.getMessage(job);
		}catch(Exception e)
		{
			e.printStackTrace();
		}
	}


	@Override
	public void connect(String serverIp, Integer serverPort)
	{
		if(primaryServer == null || servers == null)
		{
			try {
				this.start(new Machine(serverIp, serverPort));
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		try {
			buckaps =  primaryServer.getSubServers("getHosts", Notification.HOST);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public List<Machine> getBuckaps() {
		return buckaps;
	}

	public void close() {
		for(Machine mac:servers)
			mac.close();

		for(Machine mac:buckaps)
			mac.close();

	}

	public static HostInterface getInstance(Machine mac) {
		// TODO Auto-generated method stub
		if (instance == null)
			instance = new HostImpl(mac);
		return instance;


	}


	@Override
	public void connect(Machine server) {
		this.connect(server.ip, server.port);
	}

	@Override
	public void updateServerList(Machine secondary) {
		// TODO Auto-generated method stub
		try {
			this.start(secondary);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void shareMyJobs(Machine lazyHost) {

		List<Job> jobsToShare = jobController.getHalfMyJobs();
		for(Job job: jobsToShare )
		{
			try {
				job.setHead("HOST");
				job.Origin(Notification.HOST);
				lazyHost.getMessage(job);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public static HostInterface getInstance() {
		// TODO Auto-generated method stub
		return instance;
	}

	
	@Override
	public void addNewJob(Job job) {
		jobController.add(job);
	}


	public static void sort()
	{
		
			
		List<Integer>sortedNumbers = new ArrayList<Integer>(numbers);
		Collections.sort(sortedNumbers);
		int x = 0;
		
		
		for(Integer data: sortedNumbers)
		{
			x++;
			System.out.println(data);
			if(x > 200)
				break;
		}
		
		
		for(x = sortedNumbers.size()-200; x< sortedNumbers.size()-1; x++)
		{
			x++;
			System.out.println(sortedNumbers.get(x));
			
		}
		//numbers.clear();


	}
}
